package com.eternal.notification.model;

import android.annotation.SuppressLint;
import android.app.Application;

import androidx.lifecycle.MutableLiveData;
import androidx.annotation.NonNull;

import android.view.View;

import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.NavCallback;
import com.alibaba.android.arouter.launcher.ARouter;
import com.eternal.base.data.NotificationRepository;
import com.eternal.base.data.ble.BleStatue;
import com.eternal.base.database.entity.Notification;
import com.eternal.base.global.ActivityEvent;
import com.eternal.base.global.BluetoothKey;
import com.eternal.base.protocol.ProtocolTransformer;
import com.eternal.base.router.RouterActivityPath;
import com.eternal.framework.binding.command.BindingAction;
import com.eternal.framework.binding.command.BindingCommand;
import com.eternal.framework.bus.Messenger;
import com.eternal.framework.bus.RxBus;
import com.eternal.framework.component.AppManager;
import com.eternal.framework.component.BaseViewModel;
import com.eternal.framework.utils.RxUtils;
import com.eternal.framework.utils.Utils;
import com.eternal.notification.R;
import com.eternal.notification.ui.NotificationActivity;
import com.google.common.primitives.UnsignedBytes;

import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by Administrator
 * On 2020/5/9
 * Description:
 *
 * @author Administrator
 */
public class AutomationModel extends BaseViewModel {
    public AutomationModel(@NonNull Application application) {
        super(application);
        ok = Utils.getString(R.string.tip_ok);
        edit = Utils.getString(R.string.tip_edit);
        nameEdit.setValue(edit);
        startEdit.setValue(edit);
        endEdit.setValue(edit);
    }

    private String ok, edit;
    public boolean isDegree, isCreate;
    private NotificationRepository repository;
    private Notification notification;

    public MutableLiveData<String> nameEdit = new MutableLiveData<>();
    public MutableLiveData<String> startEdit = new MutableLiveData<>();
    public MutableLiveData<String> endEdit = new MutableLiveData<>();
    public MutableLiveData<String> name = new MutableLiveData<>();
    public MutableLiveData<String> start = new MutableLiveData<>();
    public MutableLiveData<String> end = new MutableLiveData<>();
    public MutableLiveData<Byte> startHour = new MutableLiveData<>();
    public MutableLiveData<Byte> startMin = new MutableLiveData<>();
    public MutableLiveData<Byte> startAp = new MutableLiveData<>();
    public MutableLiveData<Byte> endHour = new MutableLiveData<>();
    public MutableLiveData<Byte> endMin = new MutableLiveData<>();
    public MutableLiveData<Byte> endAp = new MutableLiveData<>();
    public MutableLiveData<Boolean> on = new MutableLiveData<>();
    public MutableLiveData<Boolean> off = new MutableLiveData<>();
    public MutableLiveData<Boolean> cycle = new MutableLiveData<>();
    public MutableLiveData<Boolean> tmpHum = new MutableLiveData<>();
    public MutableLiveData<Boolean> hTmpSwitch = new MutableLiveData<>();
    public MutableLiveData<Boolean> lTmpSwitch = new MutableLiveData<>();
    public MutableLiveData<Boolean> hHumSwitch = new MutableLiveData<>();
    public MutableLiveData<Boolean> lHumSwitch = new MutableLiveData<>();
    public MutableLiveData<Character> hTmp = new MutableLiveData<>();
    public MutableLiveData<Character> lTmp = new MutableLiveData<>();
    public MutableLiveData<Byte> hHum = new MutableLiveData<>();
    public MutableLiveData<Byte> lHum = new MutableLiveData<>();
    public MutableLiveData<Character> cycleOn = new MutableLiveData<>();
    public MutableLiveData<Character> cycleOff = new MutableLiveData<>();

    public View.OnClickListener onEditName = new View.OnClickListener() {
        @SuppressLint("CheckResult")
        @Override
        public void onClick(View v) {
            if (ok.equals(nameEdit.getValue())) {
                nameEdit.setValue(edit);
                if (!notification.name.equals(name.getValue())) {
                    repository.nameIsExists(notification.mac, notification.port, name.getValue())
                            .compose(RxUtils.<Boolean>bindToLifecycle(getLifecycleProvider()))
                            .subscribeOn(Schedulers.io())
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Consumer<Boolean>() {
                                @Override
                                public void accept(Boolean aBoolean) {
                                    if (aBoolean) {
                                        name.setValue(notification.name);
                                        Messenger.getDefault().sendNoMsg(NotificationActivity.SHOW_NAME_EXISTS_DIALOG);
                                    } else {
                                        if (name.getValue().isEmpty()) {
                                            name.setValue(notification.name);
                                            Messenger.getDefault().sendNoMsg(NotificationActivity.SHOW_NAME_EMPTY_DIALOG);
                                        }
                                    }
                                }
                            });
                }

            } else {
                nameEdit.setValue(ok);
            }
        }
    };

    public View.OnClickListener onEditStart = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (ok.equals(startEdit.getValue())) {
                startEdit.setValue(edit);
            } else {
                startEdit.setValue(ok);
                if (ok.equals(endEdit.getValue())) {
                    endEdit.setValue(edit);
                }
            }
        }
    };

    public View.OnClickListener onEditEnd = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (ok.equals(endEdit.getValue())) {
                endEdit.setValue(edit);
            } else {
                endEdit.setValue(ok);
                if (ok.equals(startEdit.getValue())) {
                    startEdit.setValue(edit);
                }
            }
        }
    };

    public BindingCommand<Void> onConfirm = new BindingCommand<Void>(new BindingAction() {
        @SuppressLint("CheckResult")
        @Override
        public void call() {
            BleStatue statue = repository.getConnect(notification.mac);
            if (statue != null) {
                final Notification temp = create();
                Single<Boolean> single;
                if (isCreate) {
                    single = repository.saveNotification(statue, temp);
                } else {
                    single = repository.setNotification(statue, temp);
                }
                single.compose(RxUtils.<Boolean>bindToLifecycle(getLifecycleProvider()))
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<Boolean>() {
                            @Override
                            public void accept(Boolean aBoolean) throws Exception {
                                notification = temp;
                                back();
                            }
                        });
            }
        }
    });

    public BindingCommand<Void> onCancel = new BindingCommand<Void>(new BindingAction() {
        @Override
        public void call() {
            ARouter.getInstance()
                    .build(RouterActivityPath.Detail.PAGE_DETAIL)
                    .withTransition(R.anim.left_in, R.anim.right_out)
                    .navigation(AppManager.getAppManager().currentActivity(), new NavCallback() {
                        @Override
                        public void onArrival(Postcard postcard) {
                            finish();
                        }
                    });
        }
    });

    public BindingCommand<Void> onDelete = new BindingCommand<Void>(new BindingAction() {
        @SuppressLint("CheckResult")
        @Override
        public void call() {
            Messenger.getDefault().sendNoMsg(NotificationActivity.SHOW_DELETE_DIALOG);
        }
    });

    public void init(NotificationRepository repository, String mac, byte port,
                     Notification notification, boolean isDegree) {
        this.repository = repository;
        this.isDegree = isDegree;
        isCreate = false;
        if (notification == null) {
            notification = new Notification();
            notification.name = Utils.getString(R.string.tip_default_automation_name);
            notification.model = 0x1;
            notification.open = true;
            notification.type = BluetoothKey.AUTOMATION;
            notification.mac = mac;
            notification.port = port;
            notification.hTmpC = 90;
            notification.lTmpC = 0;
            notification.hTmpF = (byte) 194;
            notification.lTmpF = 32;
            notification.hHum = 100;
            notification.lHum = 0;
            notification.tmpHum = 0xf;
            notification.start = 9 * 60;
            notification.end = 17 * 60;
            isCreate = true;
        }
        this.notification = notification;
        init(notification);
    }

    private void init(@NonNull Notification notification) {
        name.setValue(notification.name);
        switch (notification.model) {
            case 0x2:
                cycle.setValue(false);
                tmpHum.setValue(false);
                on.setValue(false);
                off.setValue(true);
                break;
            case 0x3:
                cycle.setValue(true);
                tmpHum.setValue(false);
                on.setValue(false);
                off.setValue(false);
                break;
            case 0x4:
                cycle.setValue(false);
                tmpHum.setValue(true);
                on.setValue(false);
                off.setValue(false);
                break;
            default:
                cycle.setValue(false);
                tmpHum.setValue(false);
                on.setValue(true);
                off.setValue(false);
        }
        cycleOn.setValue(notification.cycleOn);
        cycleOff.setValue(notification.cycleOff);
        initTime(notification);
        initTmpHum(notification);
    }

    private void initTime(Notification notification) {
        int hour, min;
        byte ap = 0;
        hour = notification.start / 60;
        min = notification.start % 60;
        if (hour >= 12) {
            hour -= 12;
            ap = 1;
        }
        if (hour <= 0 || hour > 12) {
            hour = 12;
        }
        String time = Utils.getString(R.string.notify_time, hour, min < 9 ? "0" + min : min, ap == 0 ? "AM" : "PM");
        --hour;
        startHour.setValue((byte) hour);
        startMin.setValue((byte) min);
        startAp.setValue(ap);
        start.setValue(time);
        hour = notification.end / 60;
        min = notification.end % 60;
        ap = 0;
        if (hour >= 12) {
            hour -= 12;
            ap = 1;
        }
        if (hour <= 0 || hour > 12) {
            hour = 12;
        }
        time = Utils.getString(R.string.notify_time, hour, min < 9 ? "0" + min : min, ap == 0 ? "AM" : "PM");
        --hour;
        endHour.setValue((byte) hour);
        endMin.setValue((byte) min);
        endAp.setValue(ap);
        end.setValue(time);
    }

    private void initTmpHum(Notification notification) {
        if (isDegree) {
            hTmp.setValue((char) notification.hTmpC);
            lTmp.setValue((char) notification.lTmpC);
        } else {
            hTmp.setValue((char) UnsignedBytes.toInt(notification.hTmpF));
            lTmp.setValue((char) UnsignedBytes.toInt(notification.lTmpF));
        }
        hHum.setValue(notification.hHum);
        lHum.setValue(notification.lHum);
        hTmpSwitch.setValue((notification.tmpHum & 8) != 0);
        lTmpSwitch.setValue((notification.tmpHum & 4) != 0);
        hHumSwitch.setValue((notification.tmpHum & 2) != 0);
        lHumSwitch.setValue((notification.tmpHum & 1) != 0);
    }

    private Notification create() {
        Notification notification = new Notification();
        notification.mac = this.notification.mac;
        notification.port = this.notification.port;
        notification.type = this.notification.type;
        notification.id = this.notification.id;
        notification.open = this.notification.open;
        if (name.getValue() == null || name.getValue().equals(Utils.getString(R.string.tip_default_automation_name))) {
            notification.name = null;
        } else {
            notification.name = name.getValue();
        }
        if (off.getValue()) {
            notification.model = 0x2;
        } else if (cycle.getValue()) {
            notification.model = 0x3;
        } else if (tmpHum.getValue()) {
            notification.model = 0x4;
        } else {
            notification.model = 0x1;
        }
        notification.tmpHum = ProtocolTransformer.setParamModel(hTmpSwitch.getValue(),
                lTmpSwitch.getValue(), hHumSwitch.getValue(), lHumSwitch.getValue());
        char temp;
        if (isDegree) {
            temp = hTmp.getValue();
            notification.hTmpC = (byte) temp;
            notification.hTmpF = (byte) ProtocolTransformer.getFah(temp);
            temp = lTmp.getValue();
            notification.lTmpC = (byte) temp;
            notification.lTmpF = (byte) ProtocolTransformer.getFah(temp);
        } else {
            temp = hTmp.getValue();
            notification.hTmpF = (byte) temp;
            notification.hTmpC = (byte) ProtocolTransformer.getDegree(temp);
            temp = lTmp.getValue();
            notification.lTmpF = (byte) temp;
            notification.lTmpC = (byte) ProtocolTransformer.getDegree(temp);
        }
        notification.hHum = hHum.getValue();
        notification.lHum = lHum.getValue();
        notification.cycleOn = cycleOn.getValue();
        notification.cycleOff = cycleOff.getValue();
        notification.start = ((char) (startHour.getValue() * 60 + 60 + startMin.getValue() + 720 * startAp.getValue()));
        notification.end = ((char) (endHour.getValue() * 60 + 60 + endMin.getValue() + 720 * endAp.getValue()));
        return notification;
    }

    @SuppressLint("CheckResult")
    public void delete() {
        BleStatue statue = repository.getConnect(notification.mac);
        if (statue != null) {
            repository.removeNotification(statue, notification)
                    .compose(RxUtils.<Boolean>bindToLifecycle(getLifecycleProvider()))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Boolean>() {
                        @Override
                        public void accept(Boolean aBoolean) {
                            if (aBoolean) {
                                back();
                            }
                        }
                    });
        }
    }

    private void back() {
        RxBus.getDefault().post(new ActivityEvent(ActivityEvent.NOTIFICATION_REFRESH));
        ARouter.getInstance()
                .build(RouterActivityPath.Detail.PAGE_DETAIL)
                .withTransition(R.anim.left_in, R.anim.right_out)
                .navigation(AppManager.getAppManager().currentActivity(), new NavCallback() {
                    @Override
                    public void onArrival(Postcard postcard) {
                        finish();
                    }
                });
    }
}
